# -*- coding: utf-8 -*-
import random
import subprocess
import time
import logging
import argparse
import requests
import base64
import cv2
import numpy as np
from appium import webdriver
# from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import sys
import locale

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')

# 设置标准输出编码为UTF-8
sys.stdout.reconfigure(encoding='utf-8')  # Python 3.7+
sys.stderr.reconfigure(encoding='utf-8')

# 设置系统区域设置
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

logger = logging

APP = "XHS"

app_package_map = {
    "XHS": ("com.xingin.xhs", ".index.v2.IndexActivityV2")
}


class XHSAppiumOperate:
    def __init__(self, **kwargs):
        self.screen_width = None
        self.screen_height = None
        self.folder_name = kwargs.get("folder_name")
        self.enable_bgm = kwargs.get("enable_bgm") != 0
        self.original = kwargs.get("original") != 0
        self.draft = kwargs.get("draft") != 0
        self.images_nums = kwargs.get("images_nums")
        self.text = self.decode_from_base64(kwargs.get("text"))
        self.content = self.decode_from_base64(kwargs.get("content"))
        self.deviceName = kwargs.get("deviceName")
        # self.group_name = None
        self.group_name = kwargs.get("group_name")
        self.appium_url = kwargs.get("appium_url")
        self.platformVersion = kwargs.get("platformVersion")
        self.systemPort = kwargs.get("systemPort")
        self.adbPort = kwargs.get("adbPort")
        self.job_id = kwargs.get("job_id")
        self.driver = None
        self.d = None
        self.max_retries = 3
        self.failure_count = 0
        self.view_count = 0
        self.like_count = 0
        self.comment_count = 0
        self.follow_count = 0

    def upload_screenshot(self, fileName):
        """
        将当前屏幕截图上传至指定接口
        :param job_id: rpaTaskid，即任务ID
        """
        try:
            # 1. 获取截图的 Base64 字符串
            screenshot_base64 = self.driver.get_screenshot_as_base64()

            if not screenshot_base64:
                logger.error("截图失败，无法获取 Base64 数据")
                return False

            # 2. 构造文件数据（模拟 multipart/form-data）
            # 使用指定的文件名格式
            files = {
                'files': [
                    {
                        "file": screenshot_base64,
                        "fileName": f"{fileName}"
                    }
                ]
            }

            # 3. 发送 POST 请求
            url = f"http://172.25.1.30:8889/social/device/task/upload/{self.job_id}"

            response = requests.post(url, json=files)

            if response.status_code == 200:
                logger.info(f"截图上传成功: {response.json()}")
            else:
                logger.error(f"截图上传失败，状态码: {response.status_code}, 响应: {response.text}")

        except Exception as e:
            logger.error(f"上传截图时发生异常: {e}")

    def run(self):
        while self.max_retries > 0:
            try:
                if self.driver:
                    self.driver.quit()
                self.connection()
                logger.info(f"设备 {self.deviceName} 连接成功")
                time.sleep(3)

                logger.info("开始执行小红书发图文任务...")
                self.script()

                break
            except Exception as e:
                logger.error(f"发生异常: {e}")
                self.failure_count += 1
                self.max_retries -= 1
            finally:
                # if not self.draft:
                #     try:
                #         remove_adb = f"adb -s {self.deviceName} -P {self.adbPort} shell rm -rf /sdcard/Movies/*"
                #         self.execute_adb_command(remove_adb)
                #     except Exception as e:
                #         logger.error(f"清理图片文件夹内的文件失败: {e}")
                if self.max_retries == 0:
                    self.normal_end()
                    raise Exception("任务失败")
        logger.info("任务结束")

    @staticmethod
    def execute_adb_command(adb_command):
        """
        执行单条 ADB 命令

        :param adb_command: 完整的 ADB 命令字符串
        :return: 命令执行结果（stdout）
        """
        try:
            logger.info(f"执行 ADB 命令: {adb_command}")
            result = subprocess.run(
                adb_command,
                shell=True,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            logger.info(f"命令执行成功: {adb_command}")
            return result.stdout.decode('utf-8')
        except subprocess.CalledProcessError as e:
            logger.error(f"命令执行失败: {adb_command}")
            logger.error(f"错误信息: {e.stderr.decode('utf-8')}")

    def initialize_device_settings(self):
        """
        执行设备初始化所需的 ADB 命令
        """
        logger.info("开始初始化设备设置")

        commands = [
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global adb_keep_usb_enabled 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global miui_optimization 0",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global tcp_keepalive 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell dumpsys battery unplug",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global background_process_limit 5",
            f"adb -s {self.deviceName} -P {self.adbPort} shell am set-standby-bucket io.appium.uiautomator2.server ACTIVE",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm trim-caches 500M",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell input keyevent KEYCODE_CLEAR",
            # f"adb -s {self.deviceName} -P {self.adbPort} shell am instrument -w -r -e debug false -e class com.github.uiautomator.stub.Stub com.github.uiautomator.test/android.support.test.runner.AndroidJUnitRunner"

        ]

        for cmd in commands:
            try:
                self.execute_adb_command(cmd)
            except Exception as e:
                logger.error(f"执行命令失败: {cmd}")
                logger.error(f"错误详情: {e}")

    def connection(self):
        self.initialize_device_settings()
        desired_caps = {
            "platformName": "Android",
            "platformVersion": self.platformVersion,
            "deviceName": self.deviceName,
            "udid": self.deviceName,
            "automationName": "UiAutomator2",
            "appPackage": app_package_map[APP][0],
            "appActivity": app_package_map[APP][1],
            "noReset": True,
            "fullReset": False,
            "systemPort": int(self.systemPort),
            "adbPort": int(self.adbPort),
            "appWaitForLaunch": True,
            "noSign": True,
            "autoLaunch": True,
            "newCommandTimeout": 500,
            "skipLogcatCapture": True,
            "disableWindowAnimation": True,
            "disableAndroidWatchers": True,
            "adbExecTimeout": 150000,
            "uiautomator2ServerInstallTimeout": 150000,
            "skipDeviceInitialization": True,
        }

        # self.driver = webdriver.Remote(self.appium_url, options=UiAutomator2Options().load_capabilities(desired_caps))
        self.driver = webdriver.Remote(self.appium_url, desired_caps)
        self.screen_width, self.screen_height = self.get_window_size()
        # self.d = u2.connect(self.deviceName)

    def script(self):
        """
        主流程：执行小红书图文发布的完整自动化流程
        包括：
            - 打开发布页面
            - 选择相册和图片
            - 填写标题与正文
            - 提交发布
        """
        try:
            logger.info("开始执行【发布图文】任务")

            # 步骤 1: 打开“发布”页面（点击首页底部的发布按钮）
            self._open_publish_page()

            # 步骤 2: 点击“从相册选择”，进入系统相册界面
            self._select_album()

            # 步骤 3: 进入“全部”相册，并选择指定文件夹中的图片
            self._choose_images()

            # 步骤 4: 确认已选图片并点击“下一步”
            self._confirm_selected_images()

            # 步骤 5: 跳过背景音乐设置（如存在“删除音乐”按钮则点击跳过）
            self._skip_background_music()

            # 步骤 6: 填写标题和正文内容
            self._fill_title_and_content()

            # 步骤 7: 最终提交图文并等待上传完成
            self._submit_post()

            logger.info("【发布图文】任务完成")

        except Exception as e:
            logger.error(f"发布图文任务失败: {e}")
            raise Exception("发布图文任务失败")

        # 返回首页并退出 Appium 会话
        # 跳转“我的”页面，获取第一条发布的笔记的分享链接（图文或者视频）
        if self.draft is not True:
            try:
                self._get_invitation_link()
            except Exception as e:
                logger.error(f"获取邀请链接失败: {e}")

    def _open_publish_page(self):
        try:
            edit_draft = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().textContains("继续编辑")',
                timeout=5
            )
            # edit_draft.click()
            logger.error(f"已经找到【编辑图文笔记吗？】弹窗，执行关闭操作")
            cancel_button = self.find_element_with_retry(
                by=AppiumBy.XPATH,
                value='(//android.widget.FrameLayout[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated"])[2]/android.widget.ImageView',
                timeout=5
            )
            cancel_button.click()
        except Exception as e:
            logger.error(f"未找到【继续编辑图文笔记吗？】弹窗: {e}")

        logger.info("正在打开【发布】页面")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.RelativeLayout[@content-desc="发布"]',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

    def _select_album(self):
        logger.info("点击【从相册选择】")
        element = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().text("从相册选择")',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

    def _choose_images(self):
        logger.info("进入【全部】相册")
        element = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().text("全部")',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

        logger.info(f"进入相册：{self.folder_name}")
        element = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value=f'new UiSelector().text("{self.folder_name}")',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

        logger.info(f"准备选择 {self.images_nums} 张图片")
        for i in range(self.images_nums - 1, -1, -1):
            index = i * 2 + 4
            logger.debug(f"正在点击第 {i + 1}/{self.images_nums} 张图 (index={index})")
            element = self.find_element_with_retry(
                by=AppiumBy.XPATH,
                value=f'(//android.widget.FrameLayout[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated"])[{index}]',
                timeout=5
            )
            element.click()
            time.sleep(random.uniform(1, 2))

    def _confirm_selected_images(self):
        logger.info("确认已选图片并进入下一步")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.TextView[@content-desc="下一步"]',
            timeout=5
        )
        element.click()
        time.sleep(10)

    def _skip_background_music(self):

        if self.enable_bgm:
            logger.warning("已选择启用背景音乐")
        else:
            logger.info("已选择不启用背景音乐")
            logger.info("尝试跳过背景音乐选择页")
            try:
                # 删除音乐按钮可能存在
                delete_music_btn = self.find_element_with_retry(
                    by=AppiumBy.ANDROID_UIAUTOMATOR,
                    value='new UiSelector().descriptionContains("删除音乐")',
                    timeout=3
                )
                delete_music_btn.click()
                logger.info("已取消背景音乐")
            except Exception as e:
                logger.warning("未找到音乐相关控件，可能无需设置音乐")

        logger.info("继续下一步")
        next_btn = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().textContains("下一步")',
            timeout=5
        )
        next_btn.click()
        time.sleep(random.uniform(8, 10))

    def _fill_title_and_content(self):
        logger.info("开始填写标题和正文内容")

        try:
            # 尝试cancel申请相册位置信息取消按钮
            cancel_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().text("取消")',
                timeout=5
            )
            cancel_button.click()
        except Exception as e:
            logger.info(f"无需申请相册位置信息: {e}")

        if self.group_name:
            self.swipe_to_next()

            logger.info("选择关联自己创建的群主")
            co_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().text("添加组件")',
                timeout=5
            )
            co_button.click()
            time.sleep(10)
            group_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().description("群聊")',
                timeout=5
            )
            group_button.click()
            time.sleep(10)

            group_name_button = self.find_element_with_retry(
                by=AppiumBy.XPATH,
                value=f'//android.widget.TextView[contains(@text, "{self.group_name}")]',
                timeout=5
            )
            group_name_button.click()
            time.sleep(10)

            confirm_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().text("确定")',
                timeout=5
            )
            confirm_button.click()
            time.sleep(10)
            # 群聊设置完成进行回退
            logger.info("群聊设置完成进行回退")
            self.driver.press_keycode(4)

        if self.original:

            logger.info("选择原创")
            setting_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().text("设置")',
                timeout=5
            )
            setting_button.click()
            time.sleep(10)
            try:
                self._find_checkbox_button()
                time.sleep(5)
                logger.info("检测是否需要勾选协议，仅仅第一次")
                try:
                    agree_button = self.find_element_with_retry(AppiumBy.ANDROID_UIAUTOMATOR,
                                                                'new UiSelector().textContains("我已阅读并同意")')

                    agree_button.click()
                    time.sleep(3)

                    button = self.find_element_with_retry(AppiumBy.ANDROID_UIAUTOMATOR,
                                                          'new UiSelector().textContains("声明原创")')
                    button.click()
                    time.sleep(10)

                except Exception as e:
                    logger.warning(f"未检测到【声明原创】按钮")
            except Exception as e:
                logger.warning(f"未找到【原创】按钮:{e}")
            finally:
                logger.info("从设置回退到编辑页")
                self.driver.press_keycode(4)

        logger.debug("点击标题输入框")

        title_input = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().textContains("标题")',
            timeout=5
        )

        title_input.click()
        time.sleep(4)
        title_input.send_keys(self.text)
        logger.info("标题内容已填写")

        logger.debug("点击正文输入框")
        content_group = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().className("android.view.ViewGroup").instance(2)',
            timeout=5
        )
        content_input = content_group.find_element(AppiumBy.XPATH, '//android.widget.EditText')

        content_input.click()
        time.sleep(1)
        self.send_keys_with_newline(content_input, self.content)
        logger.info("正文内容已填写")

    def base64_to_img(self, base64_string):
        """将 base64 字符串转为 OpenCV 图像"""
        img_data = base64.b64decode(base64_string)
        nparr = np.frombuffer(img_data, np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        return img

    def _find_checkbox_button(self):  # 视频点赞按钮

        # 将模板图片转为 base64
        # 从 base64 转回图片
        template_img = self.base64_to_img(
            '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')
        logger.info(f"使用图片识别【checkbox】按钮")
        x, y = self.find_first_template_from_top(template_img)

        # 点击找到的坐标
        self.tap(x, y)
        logger.info("成功点击【checkbox】")
        time.sleep(3)

    def tap(self, x, y):
        """点击屏幕指定坐标"""
        self.driver.tap([(x, y)], 500)

    def take_screenshot(self) -> np.ndarray:
        """截屏并转为OpenCV格式（内存方式）"""
        # 获取截图的PNG数据
        screenshot_data = self.driver.get_screenshot_as_png()

        # 将字节数据转换为numpy数组
        nparr = np.frombuffer(screenshot_data, np.uint8)

        # 解码为OpenCV图像
        image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

        if image is None:
            raise ValueError("无法解码截图数据")

        return image

    def upscale_image(self, image: np.ndarray, scale_factor: float = 2.0) -> np.ndarray:
        """放大图像"""
        if scale_factor == 1.0:
            return image

        height, width = image.shape[:2]
        new_dimensions = (int(width * scale_factor), int(height * scale_factor))

        # 使用不同的插值方法
        if scale_factor > 1.0:
            # 放大使用立方插值获得更好的效果
            upscaled_image = cv2.resize(image, new_dimensions, interpolation=cv2.INTER_CUBIC)
        else:
            # 缩小使用区域插值
            upscaled_image = cv2.resize(image, new_dimensions, interpolation=cv2.INTER_AREA)

        logging.info(f"图像尺寸从 {width}x{height} 调整为 {new_dimensions[0]}x{new_dimensions[1]}")
        return upscaled_image

    def find_first_template_from_top(self, template_img: np.ndarray, threshold: float = 0.5) -> tuple:
        """模板匹配定位从上往下的第一个匹配坐标"""
        logging.info("开始模板匹配，寻找从上往下的第一个匹配")

        # 截取屏幕并转换为 OpenCV 格式
        screen_img = self.take_screenshot()
        # upscaled_screen_img = self.upscale_image(screen_img, scale_factor=2.0)
        logging.info("截取屏幕成功")

        # 灰度化处理提升性能
        screen_gray = cv2.cvtColor(screen_img, cv2.COLOR_BGR2GRAY)
        template_gray = cv2.cvtColor(template_img, cv2.COLOR_BGR2GRAY)
        logging.info("灰度化处理完成")

        # 使用 TM_CCOEFF_NORMED 算法进行模板匹配
        res = cv2.matchTemplate(screen_gray, template_gray, cv2.TM_CCOEFF_NORMED)

        # 查找所有高于阈值的匹配点
        locations = np.where(res >= threshold)

        # # 如果没有匹配结果
        # if len(locations[0]) == 0:
        #     logging.warning(f"模板匹配失败，未找到高于阈值 {threshold} 的匹配结果")
        #     raise ValueError("未找到匹配图片")

        # 获取模板尺寸
        h, w = template_gray.shape

        # 收集所有匹配点及其匹配率
        matches_with_scores = []
        for pt in zip(*locations[::-1]):
            # 获取该点的匹配分数
            score = res[pt[1], pt[0]]
            # 计算中心点坐标
            center_x = pt[0] + w // 2
            center_y = pt[1] + h // 2
            matches_with_scores.append((pt[0], pt[1], center_x, center_y, score))

        # 按y坐标排序，确保从上到下的顺序
        matches_with_scores.sort(key=lambda x: x[1])

        # 在图像上标注所有匹配结果
        # annotated_img = screen_img.copy()

        # 为每个匹配结果绘制矩形框和文本标注
        # for i, (x, y, center_x, center_y, score) in enumerate(matches_with_scores):
        #     # 绘制矩形框
        #     top_left = (x, y)
        #     bottom_right = (x + w, y + h)
        #
        #     # 根据匹配率设置颜色（绿色到红色的渐变）
        #     # 匹配率越高颜色越绿，越低越红
        #     green_value = int(255 * score)
        #     red_value = int(255 * (1 - score))
        #     color = (red_value, green_value, 0)  # BGR格式
        #
        #     # 绘制矩形框
        #     cv2.rectangle(annotated_img, top_left, bottom_right, color, 2)
        #
        #     # 添加文本标注（坐标和匹配率）
        #     text = f"{i + 1}:({int(center_x)},{int(center_y)})-{score:.2f}"
        #     cv2.putText(annotated_img, text, (x, y - 10),
        #                 cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1, cv2.LINE_AA)

        # 打印所有匹配结果
        # logging.info(f"找到 {len(matches_with_scores)} 个匹配结果（按Y坐标排序）:")
        # for i, (x, y, center_x, center_y, score) in enumerate(matches_with_scores):
        #     logging.info(f"  匹配 {i + 1}: 原始坐标({x}, {y}), 中心坐标({center_x}, {center_y}), 匹配率: {score:.4f}")

        # 保存标注后的图像到本地
        # try:
        #     import os
        #     import tempfile
        #     # 使用临时目录保存图像
        #     root_dir = os.path.dirname(__file__)
        #     temp_dir = os.path.join(root_dir,'tmp')
        #     timestamp = int(time.time())
        #     annotated_img_path = os.path.join(temp_dir, f"template_match_result_{timestamp}.png")
        #
        #     # 保存图像
        #     cv2.imwrite(annotated_img_path, annotated_img)
        #     logging.info(f"标注后的匹配结果已保存到: {annotated_img_path}")
        # except Exception as e:
        #     logging.error(f"保存标注图像失败: {e}")

        # 选择第一个（最上面的）匹配点
        first_match = matches_with_scores[0]
        x, y, center_x, center_y, score = first_match

        logging.info(f"选择从上往下的第一个匹配结果:")
        logging.info(f"  原始坐标: ({x}, {y})")
        logging.info(f"  中心坐标: ({center_x}, {center_y})")
        logging.info(f"  匹配率: {score:.4f}")

        return center_x, center_y

    def set_clipboard_content(self, text):
        self.driver.set_clipboard_text(text)
        logger.info(f"剪贴板内容已设置为: {text}")

    def decode_from_base64(self, base64_text):
        """
        将base64编码的文本解码为原始文本
        :param base64_text: base64编码的字符串
        :return: 解码后的原始文本
        """
        try:
            # 将base64字符串解码为字节
            decoded_bytes = base64.b64decode(base64_text)
            # 将字节解码为字符串
            decoded_text = decoded_bytes.decode('utf-8')
            return decoded_text
        except Exception as e:
            print(f"解码失败: {e}")
            return None

    def send_keys_with_newline(self, element, text):
        # logger.info("正在输入内容：" + text)
        text = text.replace("\\n", "\n")

        if '#' in text:
            # 以第一个 '#' 分割字符串
            parts = text.split('#', 1)
            before_hash = parts[0]
            after_hash = '#' + parts[1]  # 保留 # 和后面的部分

            if "@" in after_hash:
                # 以第一个 '@' 分割字符串
                parts = after_hash.split('@', 1)
                before_at = parts[0]
                after_at = parts[1]  # 保留 @ 和后面的部分
                # element.send_keys("@" + after_at)
                if before_hash:
                    element.send_keys(before_hash)
                    time.sleep(1)
                for i, char in enumerate(before_at):
                    # 设置剪贴板内容为当前字符
                    self.set_clipboard_content(char)
                    time.sleep(2)  # 稍作延迟确保设置成功

                    # 模拟粘贴操作
                    # if i == 0:
                    #     element.click()
                    self.driver.press_keycode(50, 28672)  # 使用粘贴快捷键
                    # KEYCODE PASTE = 50

                    time.sleep(random.uniform(5, 8))  # 稍作延迟确保粘贴成功
                # 空格键的 Android KeyCode 是 62
                self.driver.press_keycode(62)

                # at_base64_img = "iVBORw0KGgoAAAANSUhEUgAAADgAAAA0CAYAAADfRPtlAAAEf0lEQVRoge1ZvXayShTd3723ZLo0+ADwANiHNKnwAcRerTWpUggPIHViT0yVQuiDvZPGCro0WCXNWKXJbcKswYDy57rxLnc1g8Nw9pwz588/X19fX/gf46//WoBj40zw1HEmeOo4Ezx1nAmeOv455uaUUlBKAQCbzQYAIMsyAEDTNGiadszPA8cg6Ps+giAApRSMsb1rCSHQNA26rsMwjKZFAQD8aSoXpZTCcRyEYVjpfVVVMRqNGtdqbYKMMTiOA8/zfvwmyzJ0XQchhJvmZrMBYwxBEHCzFdHpdDAajUAIqSMWRy2CcRzj9vY2pTVJkmCaJgzDQKvVOvi+7/t4fHzEdrvlz1VVxf39fSMkKxOM4xi9Xi91zwzDwHg8Li0YYwzT6RS+7/NnhBAsFovaJCsRZIxhOBymNDeZTNDpdGoJ43kebNvm8yY0WSkO7joT13Vrk8P3/XNdl8/DMITjOLX2LE2QUppyKJPJBKqq1hJChKqqmEwmfO55Ho+lVVCaoHiihmHs1VwSOnq9HtrtNtrtNnq9HhzH4UIzxjAYDHB1dYUgCIBvTYpxcTablRWTo9QdFO+IJEnwPC/zfuwLHSKSAH9zcwN8ZzcPDw98j06nw71r1TteSoPJCQOAaZq55IbD4UFyyX6iU5EkiY8JITBNk8+rmmkpgq+vr3ycl1rtelfDMOC6LlarFVarFVzXTb0rhpnduyyuWy6XZUTlKExQzC1lWc4M4p7n/QgdlmWlBFdVFZZlpRxJHlqtFs+AGGOVtFiKYAJd1zPXPD098XG/3997ZzqdDvr9/sHvit+qkudWioNZdy+O45QA3W734D5F1ojfEtO5oihMMI5jPk7MRoSYOGuaVij7SMqlfRAdjyhDUfz6il6861nVxyEUJljmQ2VMSVyb5USiKOLjKrViJQ1mVeqKovBxGIaFzGn33uatSSCaa1EUJiieXlZMIoTg8vKSz8UAnofdNVkaFGNvlZy3FMHkBOM4ztSQ6PYppbBtO1PbjDHYtp1JSHwmWoIkSZVM9G/Lsqyii9frNd7e3oAcD3hxcZESMooiPD8/4+PjA+/v74iiCL7vw7ZtrNdr/p4kSfj8/OTzJPbd3d3x+359fZ0bf/ehcrK9r+KeTqeYz+eF9kwqksFgwJ+ZpokwDFPaXCwWB1sgWShd0ZumyT2bYRjIM4AgCDCdTnM9rizLsCyLW8FgMMhNxUajUSrxLoPSBCmlqdM+VMaEYYjlcok4jkEI4c5o12EkdaEYFiRJQr/fr0wOVXsylmWlGkSu6zZW1SfdcEVRoChKJbMUUbnptHvaTTSdjoHKbcPdihs1mraMMURRlFuG1UGtxm+WJgkh6Ha7pRq/8/kcjDEQQvDy8lJVnEw00rrfbdomaLVa0HUdkiRxsnEcY7vdglL6I02TJCnVFmkCjf75MpvNKvdOZFnGeDyuFMz3oTGCCZI+ZhAEhaqKy8tL6Lp+NAfVOEERiRlut1ueUyamqmkaFEVp7F+kPByV4G/Ar6/o6+JM8NRxJnjqOBM8dfwLRP2JONpin0oAAAAASUVORK5CYII="
                # screenshot_base64 = self.driver.get_screenshot_as_base64()
                # center_x, center_y = self.find_template_position(screenshot_base64, at_base64_img)
                # if center_x is not None and center_y is not None:
                #     self.driver.tap([(center_x, center_y)])
                # else:
                #     print("未找到@的位置")
                #
                # active_element = self.driver.switch_to.active_element

                # active_element.send_keys(after_at)
                # self.execute_adb_command(f'adb -s {self.deviceName} -P {self.adbPort} shell input text {after_at}')

                self.set_clipboard_content("@" + after_at + "好")
                self.driver.press_keycode(50, 28672)
                self.driver.press_keycode(67)
                # time.sleep(6)  # 稍作延迟确保设置成功
                # self.set_clipboard_content(after_at[1:])
                # self.driver.press_keycode(50, 28672)
                time.sleep(11)
                try:
                    title = self.find_element_with_retry(
                        by=AppiumBy.XPATH,
                        value=f'//android.widget.TextView[@text="{after_at}"]',
                        timeout=5
                    )
                    title.click()
                    logger.info(f"已找到{after_at}标题")
                except Exception as e:
                    logger.info(f"第1次未找到@的标题: {e}")

                    self.driver.press_keycode(67)
                    time.sleep(11)
                    try:
                        title = self.find_element_with_retry(
                            by=AppiumBy.XPATH,
                            value=f'//android.widget.TextView[@text="{after_at}"]',
                            timeout=5
                        )
                        title.click()
                        logger.info(f"已找到{after_at}标题")
                        time.sleep(2)
                    except Exception as e:
                        logger.info(f"尝试第2次未找到@的标题: {e}")

            else:
                # 如果 before_hash 中包含 base64 编码的 emoji，进行解码

                # 发送 # 前的内容
                if before_hash:
                    element.send_keys(before_hash)
                    time.sleep(1)
                    # self.d.send_keys(f"""{before_hash}""")
                    # self.set_clipboard_content(before_hash)
                    # time.sleep(2)  # 稍作延迟确保设置成功
                    # self.driver.press_keycode(50, 28672)  # 使用粘贴快捷键
                    # time.sleep(2)  # 稍作延迟确保粘贴成功
                # 逐个字符复制粘贴 # 及之后的内容
                for i, char in enumerate(after_hash):
                    # 设置剪贴板内容为当前字符
                    self.set_clipboard_content(char)
                    time.sleep(2)  # 稍作延迟确保设置成功

                    # 模拟粘贴操作
                    # if i == 0:
                    #     element.click()
                    self.driver.press_keycode(50, 28672)  # 使用粘贴快捷键
                    # KEYCODE PASTE = 50

                    time.sleep(random.uniform(5, 8))  # 稍作延迟确保粘贴成功


        else:
            # 如果没有 #，直接发送全部内容
            element.send_keys(text)
            self.set_clipboard_content(text)
            # time.sleep(2)  # 稍作延迟确保设置成功
            # self.driver.press_keycode(50, 28672)  # 使用粘贴快捷键
            # time.sleep(2)  # 稍作延迟确保粘贴成功
            # self.d.send_keys(f"""{text}""")

    def find_template_position(self, screenshot_base64, template_base64, threshold=0.8):
        """
        在屏幕截图中查找模板图片位置并返回中心点坐标

        Args:
            screenshot_base64 (str): 屏幕截图的base64编码
            template_base64 (str): 模板图片的base64编码
            threshold (float): 匹配阈值，默认为0.8

        Returns:
            tuple: (center_x, center_y) 中心点坐标，如果未找到则返回(None, None)
        """

        # 将base64编码的模板图片转换为OpenCV图像
        template_data = base64.b64decode(template_base64)
        template_np = np.frombuffer(template_data, np.uint8)
        template = cv2.imdecode(template_np, cv2.IMREAD_GRAYSCALE)

        # 将base64编码的屏幕截图转换为OpenCV图像
        screenshot_data = base64.b64decode(screenshot_base64)
        screenshot_np = np.frombuffer(screenshot_data, np.uint8)
        screenshot = cv2.imdecode(screenshot_np, cv2.IMREAD_GRAYSCALE)

        # 执行模板匹配
        result = cv2.matchTemplate(screenshot, template, cv2.TM_CCOEFF_NORMED)

        # 查找最佳匹配位置
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

        # 如果匹配度超过阈值，则返回中心点坐标
        if max_val >= threshold:
            # 获取模板尺寸
            template_h, template_w = template.shape

            # 计算中心点坐标
            center_x = max_loc[0] + template_w // 2
            center_y = max_loc[1] + template_h // 2

            print(f"找到匹配位置: ({center_x}, {center_y}), 匹配度: {max_val}")
            return (center_x, center_y)
        else:
            print(f"未找到匹配位置，最高匹配度: {max_val}")
            return (None, None)

    def _submit_post(self):
        logger.info("准备提交图文内容")
        if self.draft:
            logger.info("已选择保存草稿")
            draft_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().textContains("草稿")',
                timeout=5
            )
            draft_button.click()
            draft_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().textContains("确定")',
                timeout=5
            )
            draft_button.click()
        else:
            publish_button = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().textContains("发布")',
                timeout=5
            )
            publish_button.click()
            logger.info("图文内容已提交，等待发布结果")
        time.sleep(20)  # 视网络情况可调整

    def _get_invitation_link(self):
        logger.info("获取刚发布内容的邀请链接")
        # 刚发布成功会出现在一个元素
        first_post = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='(//android.widget.ImageView[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated"])[1]',
            timeout=5
        )
        first_post.click()

        time.sleep(20)  # 视网络情况可调整
        self.upload_screenshot(fileName="图文详情")
        logger.info("进入【图文笔记】页面")
        self.handle_note_page()

    def handle_note_page(self):
        logger.info("执行图文笔记页操作")
        # 随机滑动 2~10 次

        invitation_button = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().resourceId("com.xingin.xhs:id/moreOperateIV")',
            timeout=5
        )
        invitation_button.click()
        logger.info("滚动寻找分享按钮")
        self.swipe_left_from_button()
        invitation_link = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().text("复制链接")',
            timeout=5
        )
        invitation_link.click()
        pasted_content = self.get_clipboard_text()
        text_link = self.extract_xhs_url(pasted_content)
        # get_clipboard_text_via_adb())
        # print("TEXT_LINK>{}<TEXT_LINK".format(text_link))
        logger.info(f"TEXT_LINK>{text_link}<TEXT_LINK")
        logger.info("获取视频笔记链接成功")

    def get_clipboard_text(self):
        # 打开系统文本？粘贴，然后读取文本内容？
        # 方法3: 创建临时输入框并粘贴
        # 寻找页面上可能的输入区域
        try:
            # 尝试寻找页面上的编辑框或输入区域
            input_element = self.find_element_with_retry(AppiumBy.XPATH,
                                                         '//android.widget.TextView[@content-desc="评论框"]')

            # 使用第一个找到的输入框
            input_element.click()
            time.sleep(1)

            # 模拟粘贴操作 (Ctrl+V)
            self.driver.press_keycode(50, 28672)  # KEYCODE_PASTE with Ctrl
            time.sleep(2)

            input_element = self.find_element_with_retry(AppiumBy.XPATH,
                                                         '//android.widget.EditText[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated"]')

            # 获取粘贴后的内容
            pasted_content = input_element.text
            # logger.info(f"通过粘贴操作获取到内容: {pasted_content}")

            return pasted_content
        except Exception as e:
            logger.warning(f"通过页面输入框粘贴获取内容失败: {e}")

    def extract_xhs_url(self, url_text):
        """
        从文本中提取小红书链接
        :param url_text: 包含链接的文本
        :return: 提取到的链接或原始链接
        """
        import re

        # 检查是否是正常的URL格式
        if url_text.startswith(('http://', 'https://')):
            return url_text

        # 如果是包含口令信息的文本，尝试提取其中的链接
        # 匹配小红书的各种链接格式:
        # 1. http://xhslink.com/...
        # 2. https://www.xiaohongshu.com/...
        url_patterns = [
            r'http[s]?://xhslink\.com/[^\s]+',
            r'http[s]?://www\.xiaohongshu\.com/[^\s]+'
        ]

        for pattern in url_patterns:
            match = re.search(pattern, url_text)
            if match:
                extracted_url = match.group(0)
                logger.info(f"从文本中提取到链接: {extracted_url}")
                return extracted_url

        # 如果没有找到链接，返回原始文本
        logger.warning(f"未在文本中找到链接，使用原始文本: {url_text}")
        return url_text

    def swipe_left_from_button(self, duration=400):
        # 定位“置顶笔记”按钮
        try:
            element = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().textContains("编辑")',
                timeout=5
            )
        except Exception as e:
            logger.error(f"找不到按钮: {e}")
            return None

        # 获取滑动的起始点和结束点
        location = element.location
        size = element.size
        center_x = location['x'] + size['width'] / 2
        center_y = location['y'] + size['height'] / 2
        start_x = center_x
        start_y = center_y
        end_x = center_x * 0.6  # 向左滑动
        end_y = center_y

        # 执行滑动操作
        self.driver.swipe(start_x, start_y, end_x, end_y, duration)
        logger.info(f"按钮向左滑动")
        self.driver.swipe(start_x, start_y, end_x, end_y, duration)

    def swipe_to_next(self):
        # 向上滑动
        self.driver.swipe(
            self.screen_width / 2,
            self.screen_height * 0.7,
            self.screen_width / 2,
            self.screen_height * 0.3,
            1000
        )

    def find_element_with_retry(self, by, value, timeout=5):
        max_retries = 2
        for attempt in range(max_retries + 1):
            try:
                element = WebDriverWait(self.driver, timeout).until(
                    EC.presence_of_element_located((by, value))
                )
                return element
            except Exception as e:
                if attempt < max_retries:
                    logger.error(f"获取元素失败，重试")
                    time.sleep(1)  # 等待1秒后重试
                else:
                    logger.error(f"获取元素失败，超过3次")
                    logger.error(f"元素名称: {value}")
                    raise NoSuchElementException(f"找不到元素: {value}")

    def get_window_size(self):
        size = self.driver.get_window_size()
        return size['width'], size['height']

    def normal_end(self):
        logger.info("返回首页并退出")
        self.driver.press_keycode(3)  # HOME 键
        self.driver.quit()


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-j', '--job_id', dest='job_id', type=str, default=None, required=True, help='target job_id')
    parser.add_argument('-u', '--appium_url', dest='appium_url', type=str, default=None, help='target appium_url')
    parser.add_argument('-d', '--deviceName', dest='deviceName', type=str, default=None, help='target deviceName')
    parser.add_argument('-s', '--systemPort', dest='systemPort', type=str, default=None, help='target systemPort')
    parser.add_argument('-a', '--adbPort', dest='adbPort', type=str, default=None, help='target adbPort')
    parser.add_argument('-p', '--platformName', dest='platformName', type=str, default=None, help='target platformName')
    parser.add_argument('-ver', '--platformVersion', dest='platformVersion', type=str, default=None,
                        help='target platformVersion')
    parser.add_argument('-v', '--variables', dest='variables', type=str, default='{}', help='target variables')
    parser.add_argument('-folder_name', '--folder_name', default="Movies", type=str)
    parser.add_argument('-images_nums', '--images_nums', type=int, required=True)
    parser.add_argument('-group_name', '--group_name', type=str, default="", help="关联的群名称")
    parser.add_argument('-text', '--text', type=str, required=True)
    parser.add_argument('-accountId', '--accountId', dest='accountId', type=str, default="000", help='target accountId')
    parser.add_argument('-executionTime', '--executionTime', dest='executionTime', type=str, default="",
                        help='executionTime')
    parser.add_argument('-content', '--content', type=str, required=True)
    parser.add_argument('-original', '--original', type=int, default=0, help="是否原创")
    parser.add_argument('-enable_bgm', '--enable_bgm', type=int, default=0, help="是否支持BGM")
    parser.add_argument('-draft', '--draft', type=int, default=0, help="是否存草稿")
    parser.add_argument('-file', '--file', type=str, required=False)

    args = parser.parse_args()
    XHSAppiumOperate(**vars(args)).run()
